package com.sanji.pay.pay.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sanji.pay.allinpay.entity.AllinPay;
import com.sanji.pay.allinpay.service.AllinPayService;
import com.sanji.pay.allinpay.util.SybUtil;
import com.sanji.pay.base.BaseResult;
import com.sanji.pay.pay.dto.PayDeal;
import com.sanji.pay.pay.entity.PayOrder;
import com.sanji.pay.pay.repository.PayOrderRepository;
import com.sanji.pay.yeepay.entity.YEEPay;
import com.sanji.pay.yeepay.service.YeePayService;
import org.apache.http.HttpEntity;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.StringEntity;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created by cbh on 2017/8/29.
 */
@Service
public class PayOrderServiceImpl implements PayOrderService {
  private Logger logger = Logger.getLogger(PayOrderServiceImpl.class);
  @Autowired
  private PayOrderRepository payOrderRepository;

  @Autowired
  private YeePayService yeePayService;

  @Autowired
  private AllinPayService allinPayService;

  @Value("${sj_mall.url}")
  public String sjMallURL;

  @Value("${sj_diy.url}")
  public String sjDiyURL;

  @Value("${sj_mall.appkey}")
  public String sjMallAppKey;

  private final static String TIME_MIN = " 00:00:00 000";

  private final static String TIME_MAX = " 23:59:59 999";

  private final static String DATE_FORMAT = "yyyy-MM-dd hh:mm:ss SSS";

  public PayOrder findByPayNumber(String payNum){
    return payOrderRepository.findByPayNum(payNum);
  }

  @Override
  public void save(PayOrder payOrder) {
    payOrderRepository.save(payOrder);
  }

  @Override
  public PayOrder findByOrderNum(String orderNum) {
    return payOrderRepository.findByOrderNum(orderNum);
  }

  @Override
  public PayOrder findByOrderNumAndSourceType(String orderNum, String sourceType) {
    return payOrderRepository.findByOrderNumAndSourceType(orderNum,sourceType);
  }

  @Override
  public String callbackToClient(PayDeal payDeal,String sourceType) {
    try {
      Map map = SybUtil.transBean2Map(payDeal);
      map.remove("hmac");
      TreeMap<String,String> treeMap = new TreeMap(map);
      payDeal.setHmac(SybUtil.sign(treeMap,sjMallAppKey));
      String param = JSONObject.toJSONString(payDeal);
      HttpEntity entity = new StringEntity(param,"utf-8");
      String url = "";
      logger.info("向客户端发送请求==========" + sourceType);
      switch (sourceType){
        case "SJ_B2B":
          url = sjMallURL+"pay/toPayMentRetrun.html";
          break;
        case "SJ_DIY":
          url = sjDiyURL+"pay/toPayMentRetrun";
          break;
        default:
          break;
      }
      String returnStr = Request.Post(url).setHeader("Content-Type","application/json").body(entity)
              .execute().returnContent().asString();
      BaseResult baseResult = JSON.parseObject(returnStr, BaseResult.class);
      logger.info("接受客户端返回是否成功=================" + baseResult.getSuccess());
//      if(!baseResult.getSuccess()){
//        Thread.sleep(1000*60);
//        restTemplate.postForEntity(url,payDeal,String.class);
//      }
      if(baseResult.getSuccess()){
        return "success";
      }else{
        return "error";
      }
    } catch (Exception e) {
      //TODO 当回调异常如何处理
      logger.error("回调异常"+e.getMessage());
//      Thread.sleep(1000*60);
//      callbackToClient(payDeal);
      return "error";
    }
  }

  @Override
  public PayDeal queryPayOrder(String orderNum) {
    PayDeal payDeal = new PayDeal();
    PayOrder payOrder = findByOrderNum(orderNum);
    switch (payOrder.getDealType()){
      case "yeePay":
        YEEPay yeePay = yeePayService.findByPayNum(payOrder.getPayNum());
        payDeal.setOrderNum(payOrder.getOrderNum());
        payDeal.setTotalCost(payOrder.getAmount());
        payDeal.setDealFee(yeePay.getAmt());
        payDeal.setDealState(yeePay.getResultCode());
        payDeal.setHmac(yeePay.getHmac() == null ? "" : yeePay.getHmac());
        payDeal.setDealId(yeePay.getTrxId());
        payDeal.setDealType("yeePay");
        payDeal.setPayTime(yeePay.getPayDate() == null ? new Date() : yeePay.getPayDate());
        payDeal.setPayType("gateway");
        payDeal.setPayee("");
        payDeal.setBankCardNo("");
        payDeal.setBankCardName("");
        payDeal.setPayNum(payOrder.getPayNum());
        break;
      case "allinPay":
        AllinPay allinPay = allinPayService.findByPayNum(payOrder.getPayNum());
        payDeal.setOrderNum(payOrder.getOrderNum());
        payDeal.setTotalCost(payOrder.getAmount());
        payDeal.setDealFee(allinPay.getTrxAmt());
        payDeal.setDealState(allinPay.getTrxStatus());
        payDeal.setHmac(allinPay.getTrxSign() == null ? "" : allinPay.getTrxSign());
        payDeal.setDealId(allinPay.getTrxId());
        payDeal.setDealType("XS");//微信、支付宝
        payDeal.setPayTime(allinPay.getPayTime() == null ? new Date() : allinPay.getPayTime());
        payDeal.setPayType("gateway");
        payDeal.setPayee("");
        payDeal.setBankCardNo("");
        payDeal.setBankCardName("");
        payDeal.setPayNum(allinPay.getPayNum());
        break;
      default:
        break;
    }
    return payDeal;
  }

  /**
   * 后台支付列表
   * @param cusId
   * @param startTime
   * @param endTime
   * @param payNum
   * @param orderNum
   * @param dealType
   * @param status
   * @param pageable
   * @return
   */
  @Override
  public Page<PayOrder> findAll(String cusId, String startTime, String endTime, String payNum, String orderNum,String dealType, Integer status, Pageable pageable) {
    Specification<PayOrder> specification = new Specification<PayOrder>(){
      @Override
      public Predicate toPredicate(Root<PayOrder> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        List<Predicate> predicates = new ArrayList<>();
        if(!StringUtils.isEmpty(cusId)){
          Predicate p1 = cb.equal(root.get("cusId"),cusId);
          predicates.add(p1);
        }
        if(!StringUtils.isEmpty(startTime) && !StringUtils.isEmpty(endTime)){
          try{
            Predicate pTime1 = cb.greaterThanOrEqualTo(root.get("createTime"),new SimpleDateFormat(DATE_FORMAT).parse(startTime+TIME_MIN));
            Predicate pTime2 = cb.lessThanOrEqualTo(root.get("createTime"),new SimpleDateFormat(DATE_FORMAT).parse(endTime+TIME_MAX));
            predicates.add(pTime1);
            predicates.add(pTime2);
          }catch (Exception e){
            logger.info("时间查询转换异常：" + e.getMessage());
          }
        }
        if(!StringUtils.isEmpty(payNum)){
          Predicate p3 = cb.like(root.get("payNum"),'%' + payNum + '%');
          predicates.add(p3);
        }
        if(!StringUtils.isEmpty(orderNum)){
          Predicate p4 = cb.like(root.get("orderNum"),'%' + orderNum + '%');
          predicates.add(p4);
        }
        if(!StringUtils.isEmpty(dealType)){
          Predicate p5 = cb.equal(root.get("dealType"),'%' + dealType + '%');
          predicates.add(p5);
        }
        if(!ObjectUtils.isEmpty(status)){
          Predicate p6;
          PayOrder.PayStatus[] payStatuses = PayOrder.PayStatus.values();
          for (PayOrder.PayStatus payStatus: payStatuses) {
            if(status == payStatus.getIndex()){
              p6 = cb.equal(root.get("status"),payStatus);
              predicates.add(p6);
            }
          }
        }
        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
      }
    };
    Page<PayOrder> payOrders = payOrderRepository.findAll(specification,pageable);
    return payOrders;
  }

  @Override
  public List<PayOrder> findAllByExport(String cusId, String startTime, String endTime) {
//    Specification<PayOrder> specification = new Specification<PayOrder>(){
//      @Override
//      public Predicate toPredicate(Root<PayOrder> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//        List<Predicate> predicates = new ArrayList<>();
//        if(!StringUtils.isEmpty(sourceType)){
//          Predicate p1 = cb.equal(root.get("sourceType"),sourceType);
//          predicates.add(p1);
//        }
//        if(!StringUtils.isEmpty(startTime) && !StringUtils.isEmpty(endTime)){
//          try{
//            Predicate pTime1 = cb.greaterThanOrEqualTo(root.get("createTime"),new SimpleDateFormat(DATE_FORMAT).parse(startTime+TIME_MIN));
//            Predicate pTime2 = cb.lessThanOrEqualTo(root.get("createTime"),new SimpleDateFormat(DATE_FORMAT).parse(endTime+TIME_MAX));
//            predicates.add(pTime1);
//            predicates.add(pTime2);
//          }catch (Exception e){
//            logger.info("时间查询转换异常：" + e.getMessage());
//          }
//        }
//
//        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
//      }
//    };
    List<PayOrder> list = new ArrayList<>();
    try{
      list = payOrderRepository.findByCusIdAndCreateTimeBetween(cusId,new SimpleDateFormat(DATE_FORMAT).parse(startTime+TIME_MIN),new SimpleDateFormat(DATE_FORMAT).parse(endTime+TIME_MAX));
    }catch (Exception e){
      logger.info("导出Excel异常" + e.getMessage());
    }
    return list;
  }
}
